use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
use std::path::PathBuf;

/// 生成器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// 默认作者信息
    pub default_author: Option<String>,

    /// 自定义模板目录
    pub template_dir: Option<PathBuf>,

    /// 输出目录偏好
    pub default_output_dir: Option<PathBuf>,

    /// 默认扩展类型
    pub default_extension_type: Option<String>,

    /// 自定义变量
    pub custom_variables: HashMap<String, String>,

    /// 生成器行为配置
    pub behavior: BehaviorConfig,
}

/// 生成器行为配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BehaviorConfig {
    /// 是否自动格式化生成的代码
    pub auto_format: bool,

    /// 是否生成示例代码
    pub generate_examples: bool,

    /// 是否生成测试文件
    pub generate_tests: bool,

    /// 是否生成文档
    pub generate_docs: bool,

    /// 是否使用彩色输出
    pub colored_output: bool,

    /// 详细日志级别
    pub verbose_level: u8,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            default_author: None,
            template_dir: None,
            default_output_dir: None,
            default_extension_type: Some("standard".to_string()),
            custom_variables: HashMap::new(),
            behavior: BehaviorConfig::default(),
        }
    }
}

impl Default for BehaviorConfig {
    fn default() -> Self {
        Self { auto_format: true, generate_examples: true, generate_tests: true, generate_docs: true, colored_output: true, verbose_level: 1 }
    }
}

impl Config {
    /// 加载配置文件
    pub fn load() -> Result<Self> {
        let config_path = Self::get_config_path()?;

        if config_path.exists() {
            let content = std::fs::read_to_string(&config_path).with_context(|| format!("读取配置文件失败: {}", config_path.display()))?;

            let config: Config = serde_yaml::from_str(&content).with_context(|| format!("解析配置文件失败: {}", config_path.display()))?;

            Ok(config)
        } else {
            // 如果配置文件不存在，返回默认配置
            Ok(Config::default())
        }
    }

    /// 保存配置文件
    pub fn save(&self) -> Result<()> {
        let config_path = Self::get_config_path()?;

        // 确保配置目录存在
        if let Some(parent) = config_path.parent() {
            std::fs::create_dir_all(parent).with_context(|| format!("创建配置目录失败: {}", parent.display()))?;
        }

        let content = serde_yaml::to_string(self).context("序列化配置失败")?;

        std::fs::write(&config_path, content).with_context(|| format!("写入配置文件失败: {}", config_path.display()))?;

        Ok(())
    }

    /// 获取配置文件路径
    fn get_config_path() -> Result<PathBuf> {
        let home_dir = dirs::home_dir().context("无法获取用户主目录")?;

        Ok(home_dir.join(".price-ext-gen").join("config.yaml"))
    }

    /// 设置配置项
    pub fn set(
        &mut self,
        key: &str,
        value: String,
    ) -> Result<()> {
        match key {
            "default_author" => {
                self.default_author = Some(value);
            },
            "template_dir" => {
                self.template_dir = Some(PathBuf::from(value));
            },
            "default_output_dir" => {
                self.default_output_dir = Some(PathBuf::from(value));
            },
            "default_extension_type" => {
                self.default_extension_type = Some(value);
            },
            "auto_format" => {
                self.behavior.auto_format = value.parse().with_context(|| format!("无效的布尔值: {}", value))?;
            },
            "generate_examples" => {
                self.behavior.generate_examples = value.parse().with_context(|| format!("无效的布尔值: {}", value))?;
            },
            "generate_tests" => {
                self.behavior.generate_tests = value.parse().with_context(|| format!("无效的布尔值: {}", value))?;
            },
            "generate_docs" => {
                self.behavior.generate_docs = value.parse().with_context(|| format!("无效的布尔值: {}", value))?;
            },
            "colored_output" => {
                self.behavior.colored_output = value.parse().with_context(|| format!("无效的布尔值: {}", value))?;
            },
            "verbose_level" => {
                self.behavior.verbose_level = value.parse().with_context(|| format!("无效的数字: {}", value))?;
            },
            _ => {
                // 自定义变量
                self.custom_variables.insert(key.to_string(), value);
            },
        }

        Ok(())
    }

    /// 获取配置项
    pub fn get(
        &self,
        key: &str,
    ) -> Option<String> {
        match key {
            "default_author" => self.default_author.clone(),
            "template_dir" => self.template_dir.as_ref().map(|p| p.display().to_string()),
            "default_output_dir" => self.default_output_dir.as_ref().map(|p| p.display().to_string()),
            "default_extension_type" => self.default_extension_type.clone(),
            "auto_format" => Some(self.behavior.auto_format.to_string()),
            "generate_examples" => Some(self.behavior.generate_examples.to_string()),
            "generate_tests" => Some(self.behavior.generate_tests.to_string()),
            "generate_docs" => Some(self.behavior.generate_docs.to_string()),
            "colored_output" => Some(self.behavior.colored_output.to_string()),
            "verbose_level" => Some(self.behavior.verbose_level.to_string()),
            _ => self.custom_variables.get(key).cloned(),
        }
    }

    /// 合并另一个配置
    pub fn merge(
        &mut self,
        other: Config,
    ) {
        if other.default_author.is_some() {
            self.default_author = other.default_author;
        }
        if other.template_dir.is_some() {
            self.template_dir = other.template_dir;
        }
        if other.default_output_dir.is_some() {
            self.default_output_dir = other.default_output_dir;
        }
        if other.default_extension_type.is_some() {
            self.default_extension_type = other.default_extension_type;
        }

        // 合并自定义变量
        self.custom_variables.extend(other.custom_variables);

        // 合并行为配置
        self.behavior = other.behavior;
    }

    /// 验证配置
    pub fn validate(&self) -> Result<()> {
        // 验证模板目录
        if let Some(ref template_dir) = self.template_dir {
            if !template_dir.exists() {
                anyhow::bail!("模板目录不存在: {}", template_dir.display());
            }
            if !template_dir.is_dir() {
                anyhow::bail!("模板路径不是目录: {}", template_dir.display());
            }
        }

        // 验证输出目录
        if let Some(ref output_dir) = self.default_output_dir {
            if let Some(parent) = output_dir.parent() {
                if !parent.exists() {
                    anyhow::bail!("输出目录的父目录不存在: {}", parent.display());
                }
            }
        }

        // 验证日志级别
        if self.behavior.verbose_level > 5 {
            anyhow::bail!("详细日志级别不能超过5");
        }

        Ok(())
    }

    /// 获取所有可配置的键
    pub fn available_keys() -> Vec<&'static str> {
        vec![
            "default_author",
            "template_dir",
            "default_output_dir",
            "default_extension_type",
            "auto_format",
            "generate_examples",
            "generate_tests",
            "generate_docs",
            "colored_output",
            "verbose_level",
        ]
    }
}

impl fmt::Display for Config {
    fn fmt(
        &self,
        f: &mut fmt::Formatter<'_>,
    ) -> fmt::Result {
        writeln!(f, "默认作者: {}", self.default_author.as_ref().unwrap_or(&"未设置".to_string()))?;
        writeln!(f, "模板目录: {}", self.template_dir.as_ref().map(|p| p.display().to_string()).unwrap_or_else(|| "内置模板".to_string()))?;
        writeln!(f, "默认输出目录: {}", self.default_output_dir.as_ref().map(|p| p.display().to_string()).unwrap_or_else(|| "当前目录".to_string()))?;
        writeln!(f, "默认扩展类型: {}", self.default_extension_type.as_ref().unwrap_or(&"standard".to_string()))?;

        writeln!(f, "\n行为配置:")?;
        writeln!(f, "  自动格式化: {}", self.behavior.auto_format)?;
        writeln!(f, "  生成示例: {}", self.behavior.generate_examples)?;
        writeln!(f, "  生成测试: {}", self.behavior.generate_tests)?;
        writeln!(f, "  生成文档: {}", self.behavior.generate_docs)?;
        writeln!(f, "  彩色输出: {}", self.behavior.colored_output)?;
        writeln!(f, "  详细级别: {}", self.behavior.verbose_level)?;

        if !self.custom_variables.is_empty() {
            writeln!(f, "\n自定义变量:")?;
            for (key, value) in &self.custom_variables {
                writeln!(f, "  {}: {}", key, value)?;
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempfile::TempDir;

    #[test]
    fn test_config_default() {
        let config = Config::default();
        assert!(config.default_author.is_none());
        assert!(config.template_dir.is_none());
        assert_eq!(config.default_extension_type, Some("standard".to_string()));
        assert!(config.behavior.auto_format);
        assert!(config.behavior.generate_tests);
    }

    #[test]
    fn test_config_set_get() {
        let mut config = Config::default();

        config.set("default_author", "Test Author".to_string()).unwrap();
        assert_eq!(config.get("default_author"), Some("Test Author".to_string()));

        config.set("auto_format", "false".to_string()).unwrap();
        assert_eq!(config.get("auto_format"), Some("false".to_string()));
        assert!(!config.behavior.auto_format);

        config.set("custom_key", "custom_value".to_string()).unwrap();
        assert_eq!(config.get("custom_key"), Some("custom_value".to_string()));
    }

    #[test]
    fn test_config_merge() {
        let mut config1 = Config::default();
        config1.default_author = Some("Author1".to_string());

        let mut config2 = Config::default();
        config2.default_author = Some("Author2".to_string());
        config2.template_dir = Some(PathBuf::from("/tmp/templates"));

        config1.merge(config2);

        assert_eq!(config1.default_author, Some("Author2".to_string()));
        assert_eq!(config1.template_dir, Some(PathBuf::from("/tmp/templates")));
    }
}
